using Microsoft.AspNetCore.SignalR;
using TerritoryGame.Application.Commands;
using TerritoryGame.Application.Queries;
using MediatR;
using System.Text.Json;
using System.Text.Json.Nodes;
using TerritoryGame.Domain.Repositories;

namespace TerritoryGame.API.Hubs
{
    public class GameHub : Hub
    {
        private readonly IMediator _mediator;
        private readonly ILogger<GameHub> _logger;
        private readonly IGameRoomRepository _roomRepository;

        // 涂色冷却配置（毫秒）
        private const int PaintCooldownMs = 100; // 0.1 秒
        private static readonly Dictionary<string, long> _lastPaintAtMsByPlayer = new();
        private static readonly object _paintLock = new();

        // 准备/结算阶段标记，避免重复启动
        private static readonly HashSet<string> _preparingRooms = new();
        private static readonly HashSet<string> _settlingRooms = new();

        public GameHub(IMediator mediator, ILogger<GameHub> logger, IGameRoomRepository roomRepository)
        {
            _mediator = mediator;
            _logger = logger;
            _roomRepository = roomRepository;
        }

        public override async Task OnConnectedAsync()
        {
            _logger.LogInformation("Client connected: {ConnectionId}", Context.ConnectionId);
            await base.OnConnectedAsync();
        }

        public override async Task OnDisconnectedAsync(Exception? exception)
        {
            _logger.LogInformation("Client disconnected: {ConnectionId}", Context.ConnectionId);
            
            // 处理玩家断开连接
            await HandlePlayerDisconnect();
            
            await base.OnDisconnectedAsync(exception);
        }

        // 加入房间
        public async Task JoinRoom(object joinData)
        {
            string? roomCode = null;
            string? playerId = null;
            
            try
            {
                // 解析参数
                var joinJson = JsonSerializer.Serialize(joinData);
                var joinDataObj = JsonSerializer.Deserialize<JsonElement>(joinJson);
                
                if (!joinDataObj.TryGetProperty("roomCode", out var roomCodeProp) || 
    !joinDataObj.TryGetProperty("playerId", out var playerIdProp) ||
    !joinDataObj.TryGetProperty("nickname", out var nicknameProp))
{
    await Clients.Caller.SendAsync("Error", "缺少必要的房间加入参数");
    return;
}
roomCode = roomCodeProp.GetString();
playerId = playerIdProp.GetString();
var nickname = nicknameProp.GetString();

                _logger.LogInformation("Player {PlayerId} joining room {RoomCode}", playerId, roomCode);

                // 存储连接信息
                Context.Items["RoomCode"] = roomCode;
                Context.Items["PlayerId"] = playerId;

                // 添加到房间组
                await Groups.AddToGroupAsync(Context.ConnectionId, roomCode);

                // 解析玩家ID
                if (!Guid.TryParse(playerId, out var playerGuid))
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "无效的玩家ID" });
                    return;
                }

                // 通过房间代码查找房间
                var roomQuery = new GetRoomByCodeQuery { RoomCode = roomCode };
                var roomResult = await _mediator.Send(roomQuery);

                if (!roomResult.Success)
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "房间不存在" });
                    return;
                }

                // 执行加入房间命令
                var command = new JoinRoomCommand
                {
                    RoomId = roomResult.RoomId.ToString(),
                    PlayerId = playerGuid,
                    PlayerNickName = nickname,
                    RoomCode = roomCode
                };

                var result = await _mediator.Send(command);

                if (result.Success)
                {
                    // 通知房间内其他玩家
                    await Clients.Group(roomCode).SendAsync("PlayerJoined", new
                    {
                        id = playerId,
                        nickname = nickname,
                        color = result.PlayerColor.Value,
                        area = 0,
                        isOnline = true,
                        joinedAt = DateTime.UtcNow
                    });

                    // 发送房间状态给新玩家
                    await SendRoomStateToClient(roomCode, roomResult.RoomId);
                }
                else
                {
                    await Clients.Caller.SendAsync("Error", new { Message = result.ErrorMessage });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error joining room. RoomCode: {RoomCode}, PlayerId: {PlayerId}, Exception: {Exception}", 
                    roomCode, 
                    playerId, 
                    ex.ToString());
                
                // 只有在真正失败时才发送错误
                if (!string.IsNullOrEmpty(roomCode) && !string.IsNullOrEmpty(playerId))
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "加入房间失败" });
                }
            }
        }

        // 离开房间
        public async Task LeaveRoom()
        {
            try
            {
                var roomCode = GetRoomCodeFromConnection();
                var playerId = GetPlayerIdFromConnection();

                if (!string.IsNullOrEmpty(roomCode) && !string.IsNullOrEmpty(playerId))
                {
                    _logger.LogInformation("Player {PlayerId} leaving room {RoomCode}", playerId, roomCode);

                    // 从房间组移除
                    await Groups.RemoveFromGroupAsync(Context.ConnectionId, roomCode);

                    // 通知其他玩家
                    await Clients.Group(roomCode).SendAsync("PlayerLeft", playerId);

                    // 持久化移除玩家
                    var roomQuery = new GetRoomByCodeQuery { RoomCode = roomCode };
                    var roomResult = await _mediator.Send(roomQuery);
                    if (roomResult.Success)
                    {
                        await RemovePlayerFromRoom(roomResult.RoomId, Guid.Parse(playerId));
                        // 如果为空房，尝试删除房间
                        await CheckAndDeleteEmptyRoom(roomCode);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error leaving room");
            }
        }

        // 开始游戏
        public async Task StartGame()
        {
            try
            {
                var roomCode = GetRoomCodeFromConnection();
                var playerId = GetPlayerIdFromConnection();

                if (string.IsNullOrEmpty(roomCode) || string.IsNullOrEmpty(playerId))
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "无效的房间或玩家信息" });
                    return;
                }

                if (!Guid.TryParse(playerId, out var playerGuid))
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "无效的玩家ID" });
                    return;
                }

                // 通过房间代码查找房间
                var roomQuery = new GetRoomByCodeQuery { RoomCode = roomCode };
                var roomResult = await _mediator.Send(roomQuery);

                if (!roomResult.Success)
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "房间不存在" });
                    return;
                }

                // 移除房主校验，任何玩家都可以开始游戏
                _logger.LogInformation("Starting game in room {RoomCode} by player {PlayerId}", roomCode, playerId);

                _logger.LogInformation("Preparing game in room {RoomCode}", roomCode);

                // 准备阶段倒计时（30秒），避免重复启动
                if (!_preparingRooms.Contains(roomCode))
                {
                    _preparingRooms.Add(roomCode);
                    _ = Task.Run(async () =>
                    {
                        try
                        {
                            var prepareSeconds = 30; // 测试模式准备阶段30秒
                            var remaining = prepareSeconds;
                            while (remaining > 0)
                            {
                                await Clients.Group(roomCode).SendAsync("TimerUpdate", remaining);
                                await Task.Delay(1000);
                                remaining--;
                            }

                            // 倒计时结束，开始游戏
                            var command = new StartGameCommand
                            {
                                RoomId = roomResult.RoomId,
                                PlayerId = playerGuid
                            };

                            var result = await _mediator.Send(command);
                            if (result.Success)
                            {
                                await Clients.Group(roomCode).SendAsync("GameStarted", new
                                {
                                    duration = result.GameDuration,
                                    players = result.Players.Select(p => new {
                                        id = p.Id,
                                        nickname = p.NickName,
                                        color = p.Color.Value,
                                        area = p.Area,
                                        isOnline = p.IsOnline
                                    }).ToList()
                                });

                                // 启动游戏计时器
                                _ = Task.Run(() => StartGameTimer(roomCode, result.GameDuration));
                            }
                            else
                            {
                                await Clients.Group(roomCode).SendAsync("Error", new { Message = result.ErrorMessage });
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "Error in preparation timer for room {RoomCode}", roomCode);
                        }
                        finally
                        {
                            _preparingRooms.Remove(roomCode);
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error starting game");
                await Clients.Caller.SendAsync("Error", new { Message = "开始游戏失败" });
            }
        }

        // 涂色动作
        public async Task PaintAction(object paintData)
        {
            try
            {
                var roomCode = GetRoomCodeFromConnection();
                var playerId = GetPlayerIdFromConnection();

                if (string.IsNullOrEmpty(roomCode) || string.IsNullOrEmpty(playerId))
                {
                    return;
                }

                if (!Guid.TryParse(playerId, out var playerGuid))
                {
                    return;
                }

                // 通过房间代码查找房间
                var roomQuery = new GetRoomByCodeQuery { RoomCode = roomCode };
                var roomResult = await _mediator.Send(roomQuery);

                if (!roomResult.Success)
                {
                    return;
                }

                // 解析涂色数据，使用 JsonElement 保证类型安全
                var paintJson = JsonSerializer.Serialize(paintData);
                var paintActionData = JsonSerializer.Deserialize<JsonElement>(paintJson);

                if (paintActionData.ValueKind != JsonValueKind.Undefined && paintActionData.ValueKind != JsonValueKind.Null)
                {
                    // 服务器端涂色冷却：0.1秒
                    var nowMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                    var throttleKey = playerId; // 以玩家ID为维度
                    bool allowed = true;
                    lock (_paintLock)
                    {
                        if (_lastPaintAtMsByPlayer.TryGetValue(throttleKey, out var lastMs))
                        {
                            if (nowMs - lastMs < PaintCooldownMs)
                            {
                                allowed = false;
                            }
                        }
                        if (allowed)
                        {
                            _lastPaintAtMsByPlayer[throttleKey] = nowMs;
                        }
                    }
                    if (!allowed)
                    {
                        return; // 丢弃过于频繁的涂色请求
                    }

                    // 创建涂色命令
                    var command = new PaintActionCommand
                    {
                        GameId = Guid.Empty, // 优先走 RoomId 查找当前进行中的游戏
                        RoomId = roomResult.RoomId,
                        PlayerId = playerGuid,
                        X = paintActionData.TryGetProperty("x", out var xEl) ? xEl.GetInt32() : 0,
                        Y = paintActionData.TryGetProperty("y", out var yEl) ? yEl.GetInt32() : 0,
                        BrushSize = paintActionData.TryGetProperty("brushSize", out var bEl) ? Math.Clamp(bEl.GetInt32(), 5, 30) : 10
                    };

                    // 执行涂色命令
                    var result = await _mediator.Send(command);

                    if (result.Success)
                    {
                        // 广播涂色动作给其他玩家
                        await Clients.OthersInGroup(roomCode).SendAsync("PaintActionReceived", new
                        {
                            PlayerId = playerId,
                            X = command.X,
                            Y = command.Y,
                            BrushSize = command.BrushSize,
                            Color = paintActionData.TryGetProperty("color", out var cEl) ? cEl.GetString() : null,
                            Tool = paintActionData.TryGetProperty("tool", out var tEl) ? tEl.GetString() : null,
                            Timestamp = paintActionData.TryGetProperty("timestamp", out var tsEl) ? tsEl.GetInt64() : DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
                        });

                        // 定期更新面积统计
                        await UpdateAreaStatistics(roomCode);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing paint action");
            }
        }

        // 重新开始游戏
        public async Task RestartGame()
        {
            try
            {
                var roomCode = GetRoomCodeFromConnection();
                var playerId = GetPlayerIdFromConnection();

                if (string.IsNullOrEmpty(roomCode) || string.IsNullOrEmpty(playerId))
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "无效的房间或玩家信息" });
                    return;
                }

                if (!Guid.TryParse(playerId, out var playerGuid))
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "无效的玩家ID" });
                    return;
                }

                // 通过房间代码查找房间
                var roomQuery = new GetRoomByCodeQuery { RoomCode = roomCode };
                var roomResult = await _mediator.Send(roomQuery);

                if (!roomResult.Success)
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "房间不存在" });
                    return;
                }

                // 移除房主校验，任何玩家都可以重新开始游戏

                _logger.LogInformation("Restarting game in room {RoomCode}", roomCode);

                // 执行重新开始游戏命令
                var command = new RestartGameCommand
                {
                    RoomId = roomResult.RoomId,
                    PlayerId = playerGuid
                };

                var result = await _mediator.Send(command);

                if (result.Success)
                {
                    // 通知所有玩家游戏重新开始
                    await Clients.Group(roomCode).SendAsync("GameStarted", new
                    {
                        duration = result.GameDuration,
                        players = result.Players.Select(p => new {
                            id = p.Id,
                            nickname = p.NickName,
                            color = p.Color.Value,
                            area = p.Area,
                            isOnline = p.IsOnline
                        }).ToList()
                    });

                    // 启动游戏计时器
                    _ = Task.Run(() => StartGameTimer(roomCode, result.GameDuration));
                }
                else
                {
                    await Clients.Caller.SendAsync("Error", new { Message = result.ErrorMessage });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error restarting game");
                await Clients.Caller.SendAsync("Error", new { Message = "重新开始游戏失败" });
            }
        }

        // 强制终止游戏
        public async Task ForceEndGame()
        {
            try
            {
                var roomCode = GetRoomCodeFromConnection();
                var playerId = GetPlayerIdFromConnection();

                if (string.IsNullOrEmpty(roomCode) || string.IsNullOrEmpty(playerId))
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "无效的房间或玩家信息" });
                    return;
                }

                if (!Guid.TryParse(playerId, out var playerGuid))
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "无效的玩家ID" });
                    return;
                }

                // 通过房间代码查找房间
                var roomQuery = new GetRoomByCodeQuery { RoomCode = roomCode };
                var roomResult = await _mediator.Send(roomQuery);

                if (!roomResult.Success)
                {
                    await Clients.Caller.SendAsync("Error", new { Message = "房间不存在" });
                    return;
                }

                _logger.LogInformation("Force ending game in room {RoomCode}", roomCode);

                // 直接调用结束游戏
                await EndGame(roomCode);
                
                // 强制解散房间时直接删除房间
                var deleteCommand = new DeleteRoomCommand { RoomCode = roomCode };
                await _mediator.Send(deleteCommand);
                await Clients.Group(roomCode).SendAsync("RoomClosed", "房间已解散");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error force ending game");
                await Clients.Caller.SendAsync("Error", new { Message = "强制终止游戏失败" });
            }
        }



        // 游戏计时器
        private async Task StartGameTimer(string roomCode, int duration)
        {
            try
            {
                _logger.LogInformation("Starting game timer for room {RoomCode} with duration {Duration}", roomCode, duration);
                Console.WriteLine($"StartGameTimer called with duration: {duration} seconds");
                
                var remainingTime = duration;
                
                while (remainingTime > 0)
                {
                    await Task.Delay(1000); // 每秒更新一次
                    remainingTime--;
                    
                    // 发送时间更新给所有玩家
                    await Clients.Group(roomCode).SendAsync("TimerUpdate", remainingTime);
                    
                    // 每10秒更新一次面积统计
                    if (remainingTime % 10 == 0)
                    {
                        await UpdateAreaStatistics(roomCode);
                    }
                }
                
                // 游戏时间到，进入结算阶段30秒
                if (!_settlingRooms.Contains(roomCode))
                {
                    _settlingRooms.Add(roomCode);
                    var settleSeconds = 30;
                    var left = settleSeconds;
                    while (left > 0)
                    {
                        await Task.Delay(1000);
                        left--;
                        await Clients.Group(roomCode).SendAsync("TimerUpdate", left);
                    }

                    // 结算结束，真正结束游戏
                    await EndGame(roomCode);
                    _settlingRooms.Remove(roomCode);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in game timer for room {RoomCode}", roomCode);
            }
        }

        // 结束游戏
        private async Task EndGame(string roomCode)
        {
            try
            {
                _logger.LogInformation("Ending game in room {RoomCode}", roomCode);
                
                // 通过房间代码查找房间
                var roomQuery = new GetRoomByCodeQuery { RoomCode = roomCode };
                var roomResult = await _mediator.Send(roomQuery);

                if (!roomResult.Success)
                {
                    return;
                }

                // 执行结束游戏命令
                var command = new EndGameCommand
                {
                    RoomId = roomResult.RoomId
                };

                var result = await _mediator.Send(command);

                if (result.Success)
                {
                    // 最终更新面积统计
                    await UpdateAreaStatistics(roomCode);
                    
                    // 通知所有玩家游戏结束
                    await Clients.Group(roomCode).SendAsync("GameEnded", new
                    {
                        players = result.Players.Select(p => new {
                            id = p.Id,
                            nickname = p.NickName,
                            color = p.Color.Value,
                            area = p.Area,
                            isOnline = p.IsOnline
                        }).ToList(),
                        winner = result.Winner == null ? null : new {
                            id = result.Winner.Id,
                            nickname = result.Winner.NickName,
                            color = result.Winner.Color.Value,
                            area = result.Winner.Area,
                            isOnline = result.Winner.IsOnline
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error ending game in room {RoomCode}", roomCode);
            }
        }

        // 更新面积统计
        private async Task UpdateAreaStatistics(string roomCode)
        {
            try
            {
                // 通过房间代码查找房间
                var roomQuery = new GetRoomByCodeQuery { RoomCode = roomCode };
                var roomResult = await _mediator.Send(roomQuery);

                if (!roomResult.Success)
                {
                    return;
                }

                // 获取游戏状态查询
                var gameStateQuery = new GetGameStateQuery
                {
                    GameId = roomResult.RoomId // 使用RoomId作为GameId
                };

                var gameStateResult = await _mediator.Send(gameStateQuery);

                if (gameStateResult.Success && gameStateResult.GameState != null)
                {
                    // 发送面积更新给所有玩家
                    // 统一使用 camelCase：areas
                    await Clients.Group(roomCode).SendAsync("AreaUpdated", new 
                    { 
                        areas = gameStateResult.GameState.Players.Select(p => new 
                        { 
                            playerId = p.Id.ToString(), 
                            area = p.Area 
                        }).ToList() 
                    });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating area statistics");
            }
        }

        // 发送房间状态给客户端
        private async Task SendRoomStateToClient(string roomCode, Guid roomId)
        {
            try
            {
                var query = new GetRoomQuery { RoomId = roomId };
                var result = await _mediator.Send(query);

                if (result.Success)
                {
                    await Clients.Caller.SendAsync("RoomStateUpdate", new
                    {
                        room = new
                        {
                            id = result.RoomId,
                            name = result.Name,
                            status = result.Status,
                            maxPlayers = result.MaxPlayers,
                            currentPlayers = result.CurrentPlayers,
                            createdBy = result.CreatedBy
                        },
                        players = result.Players.Select(p => new {
                            id = p.Id,
                            nickname = p.NickName,
                            color = p.Color.Value,
                            area = 0,
                            isOnline = p.IsOnline,
                            joinedAt = DateTime.UtcNow
                        }).ToList(),
                        status = result.Status,
                        remainingTime = result.RemainingTime,
                        gameDuration = result.GameDuration
                    });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error sending room state to client");
            }
        }

        // 处理玩家断开连接
        private async Task HandlePlayerDisconnect()
        {
            try
            {
                var roomCode = GetRoomCodeFromConnection();
                var playerId = GetPlayerIdFromConnection();

                if (!string.IsNullOrEmpty(roomCode) && !string.IsNullOrEmpty(playerId))
                {
                    // 通知其他玩家该玩家离线
                    await Clients.Group(roomCode).SendAsync("PlayerLeft", playerId);

                    // 持久化移除玩家
                    var roomQuery = new GetRoomByCodeQuery { RoomCode = roomCode };
                    var roomResult = await _mediator.Send(roomQuery);
                    if (roomResult.Success)
                    {
                        await RemovePlayerFromRoom(roomResult.RoomId, Guid.Parse(playerId));
                        // 检查房间是否为空，如果为空则删除房间
                        await CheckAndDeleteEmptyRoom(roomCode);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error handling player disconnect");
            }
        }

        // 检查并删除空房间
        private async Task CheckAndDeleteEmptyRoom(string roomCode)
        {
            try
            {
                // 通过房间代码查找房间
                var roomQuery = new GetRoomByCodeQuery { RoomCode = roomCode };
                var roomResult = await _mediator.Send(roomQuery);

                if (roomResult.Success && roomResult.CurrentPlayers == 0)
                {
                    // 房间为空，删除房间
                    var deleteCommand = new DeleteRoomCommand { RoomId = roomResult.RoomId };
                    var deleteResult = await _mediator.Send(deleteCommand);

                    if (deleteResult.Success)
                    {
                        _logger.LogInformation("Empty room {RoomCode} has been deleted", roomCode);
                        
                        // 通知房间内剩余玩家房间已关闭
                        await Clients.Group(roomCode).SendAsync("RoomClosed", new
                        {
                            Message = "房间已关闭",
                            RoomCode = roomCode
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error checking and deleting empty room {RoomCode}", roomCode);
            }
        }

        // 从连接中获取房间代码
        private string GetRoomCodeFromConnection()
        {
            return Context.Items.TryGetValue("RoomCode", out var roomCode) ? roomCode?.ToString() ?? "" : "";
        }

        // 从连接中获取玩家ID
        private string GetPlayerIdFromConnection()
        {
            return Context.Items.TryGetValue("PlayerId", out var playerId) ? playerId?.ToString() ?? "" : "";
        }

        private async Task RemovePlayerFromRoom(Guid roomId, Guid playerId)
        {
            try
            {
                await _roomRepository.RemovePlayerFromRoomAsync(roomId, playerId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error removing player from room {RoomId} {PlayerId}", roomId, playerId);
            }
        }
    }
}
